
/**
 * 
 * 可能的字母组合
 * 
 * 题目描述

每个数字关联多个字母，关联关系如下：

0 关联 “a”,”b”,”c”
1 关联 “d”,”e”,”f”
2 关联 “g”,”h”,”i”
3 关联 “j”,”k”,”l”
4 关联 “m”,”n”,”o”
5 关联 “p”,”q”,”r”
6 关联 “s”,”t”
7 关联 “u”,”v”
8 关联 “w”,”x”
9 关联 “y”,”z”
输入一串数字后，通过数字和字母的对应关系可以得到多个字母字符串（要求按照数字的顺序组合字母字符串）；

屏蔽字符串：屏蔽字符串中的所有字母不能同时在输出的字符串出现，如屏蔽字符串是abc，则要求字符串中不能同时出现a,b,c，但是允许同时出现a,b或a,c或b,c等；

给定一个数字字符串和一个屏蔽字符串，输出所有可能的字符组合；

例如输入数字字符串78和屏蔽字符串ux，输出结果为uw，vw，vx；数字字符串78，可以得到如下字符串uw，ux，vw，vx；由于ux是屏蔽字符串，因此排除ux，最终的输出是uw，vw，vx;

输入描述
第一行输入为一串数字字符串，数字字符串中的数字不允许重复，数字字符串的长度大于0，小于等于5；

第二行输入是屏蔽字符串，屏蔽字符串的长度一定小于数字字符串的长度，屏蔽字符串中字符不会重复；

输出描述
输出可能的字符串组合

注：字符串之间使用逗号隔开，最后一个字符串后携带逗号

用例
输入	78
ux
输出	uw,vw,vx,
说明	无
输入	
78
x
输出	uw,vw,
说明	无

 */

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;

/**
  * 
  题目解析
本题由两块逻辑组成：

1、根据提供的数字字符串，得到字母组合字符串。这块其实就是求组合问题，可以使用回溯算法，逻辑可以参考：LeetCode - 17 电话号码的字母组合_伏城之外的博客-CSDN博客

2、排除包含屏蔽字符串的字母组合字符串，而本题中判断一个字符串是否包含另一个字符串的逻辑是：屏蔽字符串中的所有字母不能同时在输出的字符串中出现

数字字符串中的数字不允许重复
屏蔽字符串中字符不会重复

  */
public class 可能的字母组合 {
    
    static String nums;
    static String filter;
    static String[] map = {"abc", "def", "ghi", "jkl", "mno", "pqr", "st", "uv", "wx", "yz"};
    
    static ArrayList<String> result = new ArrayList<>();
 
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
 
    nums = sc.nextLine();
    filter = sc.nextLine();
 
    System.out.println(getResult());
  }
 
  public static String getResult() {
    // 回溯算法求组合
    dfs(0, new LinkedList<>());
 
    // 拼接结果字符串
    StringBuilder sb = new StringBuilder();
    result.forEach(s -> sb.append(s).append(","));
    return sb.toString();
  }
 
  /**
   * 回溯算法求组合
   *
   * @param level 组合的层级
   * @param path 记录组合字符串
   */
  public static void dfs(int level, LinkedList<Character> path) {
    // 组合层数到达要求时，当前组合字符串完成
    if (level == nums.length()) {
      HashSet<Character> set = new HashSet<>(path);
 
      for (int i = 0; i < filter.length(); i++) {
        if (!set.contains(filter.charAt(i))) {
          StringBuilder sb = new StringBuilder();
          path.forEach(sb::append);
          result.add(sb.toString());
          return;
        }
      }
 
      return;
    }
 
    // 当前层级的数字
    int num = nums.charAt(level) - '0';
    // 该数字关联的多个字母
    String letters = map[num];
 
    // 遍历当前层级可选的字母
    for (int i = 0; i < letters.length(); i++) {
      // 选择字母加入当前组合
      char letter = letters.charAt(i);
 
      path.addLast(letter);
      // 继续组合下一个层级的字母选择
      dfs(level + 1, path);
      path.removeLast();
    }
  }
}
